home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
ARGONET
/
PD
/
FILER
/
X-FILES.ZIP
/
057
/
!X-Files
/
c
/
x-check
< prev
Wrap
Text File
|
1996-03-27
|
6KB
|
244 lines
/* x-check.c */
#include "kernel.h"
#include <stdio.h>
#include <ctype.h>
#include "swis.h"
#include <stdarg.h>
#include <setjmp.h>
#include "chunks.h"
#define FREE 0x45455246
static jmp_buf jb;
static void ASSERT(int t)
{
static _kernel_oserror assertFailed = { 0, "Assert failed" };
if (!t)
e(&assertFailed);
}
static void e(_kernel_oserror *err)
{
if (err)
longjmp(jb, (int) err);
}
static int power2(int x)
{
while (x && !(x & 1)) x >>= 1;
return x == 1;
}
static void test(int c, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (!c)
{
char buffer[256];
vsprintf(buffer, fmt, ap);
printf("x-check: %s\n", buffer);
}
va_end(ap);
}
static int okOffset(xFiles_info *pInfo, unsigned offset)
{
return (offset & (pInfo->fileHeader.allocationSize - 1)) == 0;
}
static void testChunk(xFiles_info *pInfo, unsigned cnkNum, xFiles_chunk *pChunk)
{
unsigned maxChunk;
test(pInfo->fileHeader.chunkTable.size % sizeof(xFiles_chunk) == 0,
"Bad size for chunk table %d",
pInfo->fileHeader.chunkTable.size);
maxChunk = pInfo->fileHeader.chunkTable.size / sizeof(xFiles_chunk);
test(cnkNum < maxChunk, "Bad chunk number %d", cnkNum);
if (pChunk->usage == FREE)
{
test(pChunk->offset < maxChunk,
"Chunk %d (free) bad offset %08x", cnkNum, pChunk->offset);
test(pChunk->size == FREE,
"Chunk %d (free) size is %08x (should be %08x)",
cnkNum, pChunk->size, FREE);
test(pChunk->allocSize == FREE,
"Chunk %d (free) allocSize is %08x (should be %08x)",
cnkNum, pChunk->allocSize, FREE);
}
else
{
test(okOffset(pChunk->offset),
"Chunk %d (used) bad offset %08x", cnkNum, pChunk->offset);
test(pChunk->size <= pChunk->allocSize)
"Chunk %d (used) bad size %08x (allocSize %08x)",
cnkNum, pChunk->size, pChunk->allocSize);
test(okOffset(pChunk->allocSize),
"Chunk %d (used) bad allocSize %08x", cnkNum, pChunk->allocSize);
}
}
static int chcmp(const void *a, const void *b)
{
const xFiles_chunk *ca = a;
const xFiles_chunk *cb = b;
return (int) ca->offset - (int) cb->offset;
}
static void checkChunkTable(xFiles_info *pInfo)
{
xFiles_chunk *ct;
unsigned maxChunk, freeChunk;
unsigned i, j;
maxChunk = pInfo->fileHeader.chunkTable.size / sizeof(xFiles_chunk);
ct = malloc(maxChunk * sizeof(xFiles_chunk));
ASSERT(ct != NULL);
e(xFiles_readChunk(pInfo, ct, 0, maxChunk * sizeof(xFiles_chunk), 0));
/* First follow the free chain */
freeChunk = pInfo->fileHeader.freeChunk;
while (freeChunk != 0)
{
testChunk(pInfo, freeChunk, &ct[freeChunk]);
ct[freeChunk].usage = 0;
freeChunk = ct[freeChunk].offset;
}
/* Scan for any untouched free chunks and also discard any free chunks ready
* for checking the used ones.
*/
for (i = 0, j = 0; i < maxChunk; i++)
{
if (ct[i].usage == FREE)
{
printf("x-check: free chunk %d is unlinked\n", c);
}
if (ct[i].size != free)
ct[j++] = ct[i];
}
maxChunk = j;
/* Now sort the array on offset so we can look for overlaps */
qsort(ct, maxChunk, sizeof(xFiles_chunk), chcmp);
free(ct);
}
static _kernel_oserror *check(const char *fileName, int fix)
{
xFiles_info info;
_kernel_swi_regs regs;
_kernel_oserror *err;
unsigned fileSize;
regs.r[0] = 0x4F;
regs.r[1] = (int) fileName;
if (err = _kernel_swi(OS_Find, ®s, ®s), err)
return err;
info.FileHandle = regs.r[0];
if (err = xFiles_openImage(&info), err)
goto fail;
if (err = xFiles_getLength(&info, &fileSize), err)
goto fail;
if (err = (_kernel_oserror *) setjmp(jb), err)
goto fail;
/* Validate the header */
test(info.fileHeader.hdrSize == sizeof(xFiles_header),
"Illegal hdrSize %d",
info.fileHeader.hdrSize);
test(info.fileHeader.structureVersion == xFiles_STRUCTUREVERSION,
"Illegal structureVersion %d",
info.fileHeader.structureVersion);
test(info.fileHeader.directoryVersion == xFiles_DIRECTORYVERSION,
"Illegal directoryVersion %d",
info.fileHeader.directoryVersion);
testChunk(&info, 0, &info.fileHeader.chunkTable);
test(power2(info.fileHeader.allocationUnit),
"Illegal allocationUnit %d",
info.fileHeader.allocationUnit);
testChunkTable(&info);
test(info.fileHeader.waste < fileSize,
"Illegal waste %d (fileSize is %d)",
info.fileHeader.waste, fileSize);
testStructure(&info);
if (err = xFiles_FlushFileInfo(&info), err)
goto fail;
regs.r[0] = 0;
regs.r[1] = info.fileHandle;
return _kernel_swi(OS_Find, ®s, ®s);
fail:
regs.r[0] = 0;
regs.r[1] = info.fileHandle;
(void) _kernel_swi(OS_Find, ®s, ®s);
return err;
}
int main(int argc, char *argv[])
{
int argn;
int fix = 0;
for (argn = 1; argn < argc; argn++)
{
if (*argv[argn] == '-')
{
switch (tolower(argv[argn][1]))
{
case 'f':
fix = 1;
break;
default:
fprintf(stderr, "Ignoring unknown option \"%s\"\n", argv[argn]);
break;
}
}
}
for (argn = 1; argn < argc; argn++)
{
if (*argv[argn] != '-')
{
check(argv[argn], fix);
}
}
return 0;
}